-
Notifications
You must be signed in to change notification settings - Fork 420
Properly consider blinded paths in InFlightHtlcs #4072
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Properly consider blinded paths in InFlightHtlcs #4072
Conversation
In the next commit we'll track blinded path in-flights in `InFlightHtlcs` as well as unblinded hops, so here we convert `InFlightHtlcs` to a named-field struct so that we can add more fields to it with less confusion.
Its not clear why this needs to be serialized at all (it should generally always be generated live when needed), but its serialization isn't forward-compatible, so really needs to be dropped so that we can add additional field(s) to `InFlightHtlcs`.
I've assigned @tankyleo as a reviewer! |
When paying a BOLT 12 invoice an amount greater than any one of multiple blinded paths, we need to track how much is in-flight across the paths when retrying. Here we do so, tracking blinded path usage in a new field in `InFlightHtlcs`. Fixes lightningdevkit#2737
3f57558
to
4cbd556
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4072 +/- ##
==========================================
+ Coverage 88.33% 88.36% +0.02%
==========================================
Files 177 177
Lines 131896 132011 +115
Branches 131896 132011 +115
==========================================
+ Hits 116512 116645 +133
+ Misses 12728 12704 -24
- Partials 2656 2662 +6
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
🔔 1st Reminder Hey @tankyleo! This PR has been waiting for your review. |
🔔 2nd Reminder Hey @tankyleo! This PR has been waiting for your review. |
🔔 3rd Reminder Hey @tankyleo! This PR has been waiting for your review. |
🔔 4th Reminder Hey @tankyleo! This PR has been waiting for your review. |
🔔 5th Reminder Hey @tankyleo! This PR has been waiting for your review. |
🔔 6th Reminder Hey @tankyleo! This PR has been waiting for your review. |
🔔 7th Reminder Hey @tankyleo! This PR has been waiting for your review. |
🔔 8th Reminder Hey @tankyleo! This PR has been waiting for your review. |
🔔 9th Reminder Hey @tankyleo! This PR has been waiting for your review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, just two questions for my own understanding thank you
if usage.amount_msat > hint.payinfo.htlc_maximum_msat { | ||
return u64::max_value(); | ||
} else if total_inflight_amount_msat > hint.payinfo.htlc_maximum_msat { | ||
return score_params.considered_impossible_penalty_msat; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In both cases, total amount flowing over the channel exceeds our current estimate of the channel's available liquidity, so why return u64::max_value()
vs score_params.considered_impossible_penalty_msat
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is consistent with what we do elsewhere - we only use u64::MAX
when the amount for this HTLC is too large (which shouldn't happen, the router should never try to do that) whereas we use considered_impossible_penalty_msat
if we have existing HTLCs that might saturate a channel. considered_impossible_penalty_msat
is high enough that we should always prefer any other possible route, but allows us to still try to send if we don't have any other option. In the case of in-flight HTLCs pushing us over a limit, we might as well try cause those other attempts may fail before the new HTLC gets there.
Of course for blinded paths it maybe shouldn't matter anyway - the blinded path candidates should be within the context of a single payment (because we should have a unique blinded path for each payment) so if we have no option but to over-saturate a blinded path probably we're screwed. Its still worth trying, imo, because the recipient may have given us a blinded path with a too-low htlc_maximum_msat
(ie cause they rounded-down for privacy) or could have re-used a blinded path across payments.
if tail.hops.len() > 1 { | ||
// Single-hop blinded paths aren't really "blinded" paths, as they terminate at the | ||
// introduction point. In that case, we don't need to track anything. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm ok I would have thought a single-hop blinded path is [intro] -> [destination]
; need to read up further.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea, its confusing...
👋 The first review has been submitted! Do you think this PR is ready for a second reviewer? If so, click here to assign a second reviewer. |
✅ Added second reviewer: @valentinewallace |
let mut cumulative_msat = 0; | ||
if let Some(tail) = &path.blinded_tail { | ||
cumulative_msat += tail.final_value_msat; | ||
if tail.hops.len() > 1 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this method should take into account trampoline hops, might be easy to do here
if tail.hops.len() > 1 { | ||
// Single-hop blinded paths aren't really "blinded" paths, as they terminate at the | ||
// introduction point. In that case, we don't need to track anything. | ||
let last_hop = path.hops.last().unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The last unblinded hop could be the last trampoline hop instead, IIUC
inflight_htlc_msat: 0, | ||
effective_capacity: EffectiveCapacity::HintMaxHTLC { amount_msat: 500 }, | ||
}; | ||
inflight_scorer.channel_penalty_msat(&candidate, empty_usage, &()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this value be checked?
When paying a BOLT 12 invoice an amount greater than any one of
multiple blinded paths, we need to track how much is in-flight
across the paths when retrying. Here we do so, tracking blinded
path usage in a new field in
InFlightHtlcs
.Fixes #2737